import 'dart:io';

import 'dart:typed_data';

class ChatWs {
  static ChatWs _instance;

  factory ChatWs() {
    _instance ??= ChatWs._();
    return _instance;
  }

  ChatWs._();

  WebSocket _ws;

  Future connect() async {
    if (!isConnect) {
      await _createConnect();
    }
  }

  bool get isConnect {
    if (_ws == null) {
      return false;
    }
    return _ws.closeCode == null;
  }

  Future disconnect() async {
    _ws?.close();
  }

  Future _createConnect() async {
    try {
      _ws = await WebSocket.connect("ws://localhost:10000/ping");
      _ws?.asBroadcastStream()?.listen(
        _onReiceve,
        onError: (err) {},
        onDone: () {
          _ws = null;
          _onStateChange();
        },
      );
      _onStateChange();
    } catch (e) {
      _ws = null;
      _onStateChange();
    }
  }

  void _onStateChange() {
    _observerSet.forEach((observer) {
      observer.onConnectStateChange(this);
    });
  }

  Future sendMsg(Uint8List msg) async {
    _ws?.add(msg.toList());
  }

  Set<WebSocketObserver> _observerSet = Set();

  void addObserver(WebSocketObserver observer) {
    _observerSet.add(observer);
  }

  void removeObserver(WebSocketObserver observer) {
    _observerSet.remove(observer);
  }

  void _onReiceve(event) {
    _observerSet.forEach((observer) {
      observer.onReceiveMsg(event);
    });
  }
}

mixin WebSocketObserver {
  void onReceiveMsg(Uint8List data);

  void onConnectStateChange(ChatWs chatWs);
}
